import { unref } from 'vue';
import type { Recordable, UseFormValuesContext } from '../types/form';
import { cloneDeep, isArray, isFunction, isObject, isString, set } from 'lodash-es';
import { isNullOrUnDef } from '../common/is';
import { dateUtil } from '../types/formEvents';
/**
 * @description deconstruct array-link key. This method will mutate the target.
 */
function tryDeconstructArray(key: string, value: any, target: Recordable) {
  const pattern = /^\[(.+)\]$/;
  if (pattern.test(key)) {
    const match = key.match(pattern);
    if (match && match[1]) {
      const keys = match[1].split(',');
      value = Array.isArray(value) ? value : [value];
      keys.forEach((k, index) => {
        set(target, k.trim(), value[index]);
      });
      return true;
    }
  }
}

/**
 * @description deconstruct object-link key. This method will mutate the target.
 */
function tryDeconstructObject(key: string, value: any, target: Recordable) {
  const pattern = /^\{(.+)\}$/;
  if (pattern.test(key)) {
    const match = key.match(pattern);
    if (match && match[1]) {
      const keys = match[1].split(',');
      value = isObject(value) ? value : {};
      keys.forEach((k) => {
        set(target, k.trim(), value[k.trim()]);
      });
      return true;
    }
  }
}

export function useFormValues({
  defaultValueRef,
  getSchema,
  formModel,
  getProps,
}: UseFormValuesContext) {
  function initDefault() {
    const schemas = unref(getSchema);
    const obj: Recordable = {};
    schemas.forEach((item) => {
      const { defaultValue } = item;
      if (!isNullOrUnDef(defaultValue)) {
        obj[item.field] = defaultValue;

        if (formModel[item.field] === undefined) {
          formModel[item.field] = defaultValue;
        }
      }
    });
    const { mergeDynamicData } = unref(getProps);
    if (isObject(mergeDynamicData)) {
      Object.keys(mergeDynamicData).forEach((e: string) => {
        formModel[e] = mergeDynamicData[e];
      });
    }
    defaultValueRef.value = cloneDeep(obj);
  }
  // Processing form values
  function handleFormValues(values: Recordable) {
    const schemas = unref(getSchema);
    if (!isObject(values)) {
      return {};
    }

    const res: Recordable = {};
    for (const item of Object.entries(values)) {
      let [, value] = item;
      const [key] = item;
      if (!key || !value || (isArray(value) && value.length === 0) || isFunction(value)) {
        continue;
      }

      const transformDateFunc = unref(getProps).transformDateFunc;
      if (isObject(value)) {
        value = transformDateFunc?.(value);
      }

      if (isArray(value) && value[0]?.format && value[1]?.format) {
        value = value.map((itemd) => transformDateFunc?.(itemd));
      }
      // Remove spaces
      if (isString(value)) {
        value = value.trim();
      }

      // 如果是数组
      if (key.includes(',')) {
        schemas.forEach((items: any) => {
          // 满足是时间
          if (items.field == key && items.component == 'DatePicker') {
            const format =
              (isFunction(items.componentProps)
                ? items.componentProps().format
                : items.componentProps?.format) || 'YYYY-MM-DD hh:mm:ss';
            const keyArr = key.replace(/\[|]/g, '').split(',');
            keyArr.forEach((e: string, eindex: number) => {
              set(res, e, formatTime(value[eindex], format));
            });
          } else if (items.field == key) {
            const keyArr = key.replace(/\[|]/g, '').split(',');
            keyArr.forEach((e: string, eindex: number) => {
              set(res, e, value[eindex]);
            });
          }
        });
      } else {
        if (!tryDeconstructArray(key, value, res) && !tryDeconstructObject(key, value, res)) {
          // 没有解构成功的，按原样赋值
          set(res, key, value);
        }
      }
    }
    return res;
  }

  function formatTime(time: string, format: string) {
    if (format === 'timestamp') {
      return dateUtil(time).unix();
    } else if (format === 'timestampStartDay') {
      return dateUtil(time).startOf('day').unix();
    }
    return dateUtil(time).format(format);
  }

  return { initDefault, handleFormValues };
}
